#include "PUMeasure.h"

CPUMeasure::CPUMeasure(void)
{
	bEnd=FALSE;
	dwLastThreadTime = 0;
	dwLastTickTime = 0;
	ThreadCreate();
}

CPUMeasure::~CPUMeasure(void)
{
	bEnd=TRUE;
	KillThread();
}

DWORD CPUMeasure::GetThreadTick(FILETIME* a, FILETIME* b)
{
	__int64 a64 = 0;
	__int64 b64 = 0;
	a64 = a->dwHighDateTime;
	a64 <<= 32;
	a64 += a->dwLowDateTime;

	b64 = b->dwHighDateTime;
	b64 <<= 32;
	a64 += b->dwLowDateTime;

	a64 += b64;

	// nano sec to milli sec
	a64 /= 10000;

	return (DWORD)a64;
}

bool CPUMeasure::ThreadCreate(void)
{
	DWORD ThreadID;
	hIdleThread = CreateThread(NULL, 0,&CPUMeasure::idleThread, (LPVOID)this, CREATE_SUSPENDED, &ThreadID);
	if (hIdleThread == NULL)
		return false;

	SetThreadPriority(hIdleThread, THREAD_PRIORITY_IDLE);
	//first measure
	dwLastTickTime = GetTickCount();
	dwLastThreadTime = 0;
	ResumeThread(hIdleThread);
	return false;
}
void CPUMeasure::KillThread()
{
	if (hIdleThread)
	{
		bEnd = true;
		ResumeThread(hIdleThread);
		if (WaitForSingleObject(hIdleThread, 3000) != WAIT_OBJECT_0)
			TerminateThread(hIdleThread,0);
		hIdleThread = NULL;
	}
}

DWORD CPUMeasure::idleThread(LPVOID lpParameter)
{
	CPUMeasure * me=(CPUMeasure *)lpParameter;
	while (!me->bEnd)
		;
	return 0;
}
void CPUMeasure::Measure()
{
	DWORD dwCurrentThreadTime =0;
	DWORD dwCurrentTickTime = 0;

	FILETIME ftCreationTime;
	FILETIME ftExitTime;
	FILETIME ftKernelTime;
	FILETIME ftUserTime;

	DWORD dwCpuPower;

	// search status
	SuspendThread(hIdleThread);

	dwCurrentTickTime = GetTickCount();
	GetThreadTimes(hIdleThread, &ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime);
	dwCurrentThreadTime = GetThreadTick(&ftKernelTime, &ftUserTime);

	// calculate cpu power
	if( dwCurrentTickTime != dwLastTickTime || dwLastThreadTime != 0 || dwLastTickTime != 0)
		dwCpuPower = 100 - (((dwCurrentThreadTime - dwLastThreadTime) * 100) / (dwCurrentTickTime - dwLastTickTime));
	else
		dwCpuPower = 0;	// avoid 0div

	chCPUHistory=(char)dwCpuPower;

	// save status
	dwLastTickTime = GetTickCount();
	dwLastThreadTime = dwCurrentThreadTime;

	ResumeThread(hIdleThread);
}